package com.loe.mvp.ext_view

import android.os.Handler
import android.os.Looper
import android.text.*
import android.text.method.DigitsKeyListener
import android.text.style.ForegroundColorSpan
import android.view.MotionEvent
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.EditText
import android.widget.TextView
import androidx.core.text.HtmlCompat
import androidx.viewpager.widget.ViewPager
import com.chad.library.adapter.base.BaseViewHolder
import com.loe.mvp.ext_java.*
import com.loe.mvp.ext_view.DelayTask
import com.loe.mvp.util.DecimalLimitFilter
import org.json.JSONArray
import org.json.JSONObject

inline var View?.visible: Boolean
    get() = if (this != null) this.visibility == View.VISIBLE else false
    set(value)
    {
        this?.visibility = if (value) View.VISIBLE else View.GONE
    }

fun TextView?.setText(o: Any)
{
    this?.text = o.toString()
}

inline val View?.string: String
    get() = if (this is TextView) text.trim().toString() else ""

inline val View?.stringOrHint: String
    get() = if (this is TextView) text.trim().toString().ifEmpty { hint.toString() } else ""

inline val View?.stringNull: String?
    get() = string.ifEmpty { null }

inline val View?.int: Int
    get() = try
    {
        string.toInt()
    } catch (e: Exception)
    {
        0
    }

inline var View?.html: String
    get() = if (this is TextView) text.trim().toString() else ""
    set(value)
    {
        (this as TextView).text = value.html
    }

inline val View?.double: Double
    get() = try
    {
        string.toDouble()
    } catch (e: Exception)
    {
        0.0
    }

inline val View?.moneyLong: Long
    get() = double.moneyLong

inline val View?.tagString: String?
    get() = this?.tag?.toString()?.trim() ?: null


inline val View?.tagStringNull: String?
    get()
    {
        val s = this?.tag?.toString()?.trim()
        return if (s == null || s.isEmpty()) null else s
    }

inline val View?.tagJsonArray: JSONArray?
    get() = if (this?.tag is JSONArray) this.tag as JSONArray else try
    {
        JSONArray(this?.tag?.toString())
    } catch (e: Exception)
    {
        null
    }

inline val View?.tagJson: JSONObject?
    get() = if (this?.tag is JSONObject) this.tag as JSONObject else try
    {
        JSONObject(this?.tag?.toString())
    } catch (e: Exception)
    {
        null
    }

inline val TextView?.isEmpty get() = string.isEmpty()
inline val TextView?.isNotEmpty get() = string.isNotEmpty()

fun TextView?.putText(s: String)
{
    this.setText(s)
    if (this is EditText) setSelection(s.length)
}

fun TextView?.setMaxLen(i: Int)
{
    this?.filters = arrayOf(InputFilter.LengthFilter(i))
}

fun TextView?.setFilter(s: String)
{
    this?.keyListener = DigitsKeyListener.getInstance(s)
}

fun TextView.setSpecTextColor(oriText: String, specText: String, color: String)
{
    if (oriText.isEmpty() || specText.isEmpty() || !oriText.contains(specText))
    {
        text = oriText
        return
    }

    val colorText = specText.c(color)
    html = oriText.replace(specText, colorText)
}

inline var View?.layoutHeight: Int
    get() = this?.height ?: 0
    set(value)
    {
        val params = this?.layoutParams
        params?.height = value
        this?.layoutParams = params
    }

inline var View?.layoutWidth: Int
    get() = this?.width ?: 0
    set(value)
    {
        val params = this?.layoutParams
        params?.width = value
        this?.layoutParams = params
    }

fun View?.setWithHeight(w: Int, h: Int)
{
    val params = this?.layoutParams
    params?.width = w
    params?.height = h
    this?.layoutParams = params
}

/**
 * 判断是否点击了某个View
 */
fun View?.inRangeOfView(ev: MotionEvent?): Boolean
{
    if (this != null && ev != null)
    {
        val location = IntArray(2)
        getLocationOnScreen(location)
        val x = location[0]
        val y = location[1]
        return !(ev.x < x || ev.x > x + this.width || ev.y < y || ev.y > y + this.height)
    }
    return false
}

fun View?.setDelayClickListener(delay: Long = 0, interval: Long = 1200, onClick: (v: View) -> Unit)
{
    var t = 0L
    this?.setOnClickListener()
    {
        if (System.currentTimeMillis() - t > interval)
        {
            postDelayed({ onClick(it) }, delay)
            t = System.currentTimeMillis()
        }
    }
}

fun View?.setOnDownListener(onDown: (v: View) -> Unit)
{
    this?.setOnTouchListener()
    { v, event ->
        if (event.action == MotionEvent.ACTION_DOWN) onDown(v)
        true
    }
}


fun TextView?.setOnEditorSearchListener(listener: () -> Unit)
{
    this?.setOnEditorActionListener()
    { _, id, _ ->
        if (id == EditorInfo.IME_ACTION_SEARCH)
        {
            listener()
            return@setOnEditorActionListener true
        }
        false
    }
}

fun TextView?.setOnEditorOkListener(ok: () -> Unit)
{
    this?.setOnEditorActionListener()
    { _, actionId, _ ->
        if (actionId == EditorInfo.IME_ACTION_DONE)
        {
            ok()
        }
        false
    }
}

fun TextView?.addTextAfterListener(after: (s: String) -> Unit)
{
    this?.addTextChangedListener(object : TextWatcher
    {
        override fun afterTextChanged(s: Editable?)
        {
            after(s.toString())
        }

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int)
        {
        }

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int)
        {
        }
    })
}

fun ViewPager?.addOnPageSelectedListener(onSelect: (index: Int) -> Unit)
{
    this?.addOnPageChangeListener(object : ViewPager.OnPageChangeListener
    {
        override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int)
        {
        }

        override fun onPageSelected(position: Int)
        {
            onSelect(position)
        }

        override fun onPageScrollStateChanged(state: Int)
        {
        }
    })
}

fun ViewPager?.addOnPageStateListener(onState: (state: Int) -> Unit)
{
    this?.addOnPageChangeListener(object : ViewPager.OnPageChangeListener
    {
        override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int)
        {
        }

        override fun onPageSelected(position: Int)
        {
        }

        override fun onPageScrollStateChanged(state: Int)
        {
            onState(state)
        }
    })
}

fun TextView?.addTextAfterListener(delay: Long, after: (s: String) -> Unit)
{
    var task: DelayTask? = null
    addTextAfterListener()
    {
        task?.stop()
        task = object : DelayTask(delay)
        {
            override fun run()
            {
                after(it)
            }
        }
        task?.start()
    }
}

/**
 * 添加金额输入限制
 */
fun EditText?.addMoneyLimit(after: ((s: String) -> Unit)? = null)
{
    this?.filters = arrayOf(DecimalLimitFilter())
    this?.addTextChangedListener(object : TextWatcher
    {
        override fun afterTextChanged(s: Editable?)
        {
            val priceString = s.toString()
            // 头部输入“0”逻辑
            if (priceString.length > 1 && priceString[0] == '0' && priceString[1] != '.')
            {
                setText(priceString.double.string)
                setSelection(length())
                return
            }
            // 头部输入“.”逻辑
            if (priceString.isNotEmpty() && priceString[0] == '.')
            {
                setText("0$priceString")
                setSelection(2)
                return
            }
            // 粘贴、中途加“.”等情况下小数位数过大纠正
            val di = priceString.indexOf(".")
            if (di > 0 && di < priceString.length - 3)
            {
                setText(priceString.substring(0, di + 3))
                setSelection(di + 1)
                return
            }

            after?.invoke(s.toString())
        }

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int)
        {
        }

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int)
        {
        }
    })
}

internal abstract class DelayTask(var delay: Long) : Handler(Looper.getMainLooper())
{
    private var runnable = Runnable { this@DelayTask.run() }

    fun start()
    {
        if (delay == 0L)
        {
            post(runnable)
        } else
        {
            postDelayed(runnable, delay)
        }
    }

    fun stop()
    {
        removeCallbacks(runnable)
    }

    protected abstract fun run()
}

fun BaseViewHolder.addOnClickView(vararg views: View)
{
    addOnClickListener(*(views.map { it.id }.toIntArray()))
}